#include <stdio.h>
#include <string.h>
#include "dbg.h"

#define COUNTC 16

void
printfstr (const char *format, char *from)
{
  printf (format, "标记");
  /*
  while (*from)
    {
      putchar (*from);
      from++;
    }
    */
  for (int i = 0; i < COUNTC; i++)
	  printf("%c", from[i]);

  printf ("\n");

}

int
normal_copy (char *from, char *to, int count)
{
  printf ("normal_copy from is %s\n", from);
  printf ("normal_copy to is %s\n", to);
  int i = 0;

  for (i = 0; i < count; i++)
    {
      to[i] = from[i];
      printf ("i%d:%s\n", i, to);
    }

  return i;
}

int
duffs_device (char *from, char *to, int count)
{
  {
    printf ("duffs_device from is %s\n", from);
    printf ("duffs_device to is %s\n", to);
    int n = (count + 7) / 8;

    switch (count % 8)
      {
      case 0:
	do
	  {
	    printf ("n is %d\n", n);
	    *to++ = *from++;
	    printfstr ("case0:%s\n", to);
      case 7:
	    *to++ = *from++;
	    printfstr ("case7:%s\n", to);
      case 6:
	    *to++ = *from++;
	    printfstr ("case6:%s\n", to);
      case 5:
	    *to++ = *from++;
	    printfstr ("case5:%s\n", to);
      case 4:
	    *to++ = *from++;
	    printfstr ("case4:%s\n", to);
      case 3:
	    *to++ = *from++;
	    printfstr ("case3:%s\n", to);
      case 2:
	    *to++ = *from++;
	    printfstr ("case2:%s\n", to);
      case 1:
	    *to++ = *from++;
	    printfstr ("case1:%s\n", to);
	  }
	while (--n > 0);
      }
  }

  return count;
}

int
zeds_device (char *from, char *to, int count)
{
  {
    printf ("zeds_device from is %s\n", from);
    printf ("zeds_device to is %s\n", to);
    int n = (count + 7) / 8;

    switch (count % 8)
      {
      case 0:
      again:*to++ = *from++;
	printf ("case0:%s\n", to);
      case 7:
	*to++ = *from++;
	printf ("case7:%s\n", to);
      case 6:
	*to++ = *from++;
	printf ("case6:%s\n", to);
      case 5:
	*to++ = *from++;
	printf ("case5:%s\n", to);
      case 4:
	*to++ = *from++;
	printf ("case4:%s\n", to);
      case 3:
	*to++ = *from++;
	printf ("case3:%s\n", to);
      case 2:
	*to++ = *from++;
	printf ("case2:%s\n", to);
      case 1:
	*to++ = *from++;
	printf ("case1:%s\n", to);
	if (--n > 0)
	  goto again;
      }
  }

  return count;
}

int
valid_copy (char *data, int count, char expects)
{
  int i = 0;
  for (i = 0; i < count; i++)
    {
      if (data[i] != expects)
	{
	  log_err ("[%d] %c != %c", i, data[i], expects);
	  return 0;
	}
    }

  return 1;
}

int
main (int argc, char *argv[])
{
  char from[COUNTC] = { 'a' };
  printfstr ("from1:%s\n", from);
  char to[COUNTC] = { 'c' };
  int rc = 0;

  // setup the from to have some stuff
  memset (from, 'x', COUNTC - 1);
  printfstr ("from2:%s\n", from);
  // set it to a failure mode
  memset (to, 'y', COUNTC - 1);
  check (valid_copy (to, COUNTC - 1, 'y'), "Not initialized right.");
  //
  // use normal copy to 
  rc = normal_copy (from, to, COUNTC);
  printfstr ("from3:%s\n", from);
  check (rc == COUNTC, "Normal copy failed: %d", rc);
  check (valid_copy (to, COUNTC - 1, 'x'), "Normal copy failed.");
  //
  // reset
  memset (to, 'y', COUNTC - 1);
  //
  // duffs version
  rc = duffs_device (from, to, COUNTC);
  printfstr ("from4:%s\n", from);
  check (rc == COUNTC, "Duff's device failed: %d", rc);
  check (valid_copy (to, COUNTC - 1, 'x'), "Duff's device failed copy.");
  //
  // reset
  memset (to, 'y', COUNTC - 1);
  //
  // my version 
  rc = zeds_device (from, to, COUNTC);
  printfstr ("from5:%s\n", from);
  //                              
  check (rc == COUNTC, "Zed's device failed: %d", rc);
  //    
  check (valid_copy (to, COUNTC - 1, 'x'), "Zed's device failed copy.");
  //
  // 
  return 0;
  //                                                                                    
error:
  // 
  return 1;
  //                          
}
